<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="ON128" id="ON128"><span data-lake-id="u21bea6d7" id="u21bea6d7">典型回答</span></h1>
  <p data-lake-id="ud0e0319b" id="ud0e0319b"><br></p>
  <p data-lake-id="uaabb8319" id="uaabb8319"><span data-lake-id="ubd5f741b" id="ubd5f741b">AQS（AbstractQueuedSynchronizer）是Java中实现锁和同步器的基础类，通过FIFO双向队列来管理等待线程和阻塞线程，实现线程之间的协作。</span></p>
  <p data-lake-id="u41c1029b" id="u41c1029b"><span data-lake-id="u5fe81b4c" id="u5fe81b4c">​</span><br></p>
  <p data-lake-id="ud87c467b" id="ud87c467b"><span data-lake-id="u3a7717c3" id="u3a7717c3">​</span><br></p>
  <p data-lake-id="u9beff697" id="u9beff697"><span data-lake-id="u1b11baaf" id="u1b11baaf">AQS中线程等待和唤醒主要依赖park和unpark实现的。</span></p>
  <p data-lake-id="udc4a36f7" id="udc4a36f7"><br></p>
  <p data-lake-id="u4be5dc0f" id="u4be5dc0f"><span data-lake-id="uee3b8667" id="uee3b8667">当一个线程尝试获取锁或者同步器时，如果获取失败，AQS会将该线程封装成一个Node并添加到等待队列中，然后通过LockSupport.park()将该线程阻塞。</span></p>
  <p data-lake-id="u41510b9b" id="u41510b9b"><span data-lake-id="u9f31b725" id="u9f31b725">​</span><br></p>
  <p data-lake-id="u3142986c" id="u3142986c"><span data-lake-id="u11ecc4e7" id="u11ecc4e7">当一个线程释放锁或者同步器时，AQS会通过LockSupport.unpark()方法将等待队列中的第一个线程唤醒，并让其重新尝试获取锁或者同步器。</span></p>
  <p data-lake-id="ubad431f1" id="ubad431f1"><span data-lake-id="u1b46b93a" id="u1b46b93a">​</span><br></p>
  <p data-lake-id="u26654af8" id="u26654af8"><span data-lake-id="ua15d09b3" id="ua15d09b3">除了基本的等待和唤醒机制，AQS还提供了条件变量（Condition）的实现，用于在某些条件不满足时让线程等待，并在条件满足时唤醒线程。具体实现是通过创建一个等待队列，将等待的线程封装成Node并添加到队列中，然后将这些线程从同步队列中移除，并在条件满足时将等待队列中的所有线程唤醒。</span></p>
  <p data-lake-id="u6245670c" id="u6245670c"><span data-lake-id="u1a0fc343" id="u1a0fc343">​</span><br></p>
  <h1 data-lake-id="AzBH8" id="AzBH8"><span data-lake-id="uff399f42" id="uff399f42">扩展知识</span></h1>
  <p data-lake-id="u864b5dce" id="u864b5dce"><br></p>
  <h2 data-lake-id="Wwlvs" id="Wwlvs"><span data-lake-id="u13d6fbdc" id="u13d6fbdc">park&amp;unpark</span></h2>
  <p data-lake-id="u2e65008c" id="u2e65008c"><br></p>
  <p data-lake-id="ue262eeba" id="ue262eeba"><span data-lake-id="uc28437a2" id="uc28437a2">Java中的park()和unpark()方法是一对用于线程等待和唤醒的方法，一般用于实现锁、信号量、线程池等高级并发组件。</span></p>
  <p data-lake-id="u6a2cba86" id="u6a2cba86"><span data-lake-id="ua301bc52" id="ua301bc52">​</span><br></p>
  <p data-lake-id="ub6d76c81" id="ub6d76c81"><span data-lake-id="uf643466c" id="uf643466c">park()</span><span data-lake-id="ub67e198e" id="ub67e198e">方法可以使调用线程进入休眠状态，等待被其他线程唤醒，具体实现会让线程进入等待队列中，等待被唤醒。</span><span data-lake-id="u48d7bd63" id="u48d7bd63">park()</span><span data-lake-id="u3853ce30" id="u3853ce30">方法可以通过传入一个Object类型的参数进行阻塞，这个参数是用来标识这个线程阻塞的原因，方便调试和排查问题。</span></p>
  <p data-lake-id="u6e8552d5" id="u6e8552d5"><span data-lake-id="u068c9c08" id="u068c9c08">​</span><br></p>
  <p data-lake-id="u40ee26cd" id="u40ee26cd"><span data-lake-id="u04e4d699" id="u04e4d699">unpark()方法可以使某个被阻塞的线程被唤醒，让其继续执行。unpark()方法需要传入一个Thread类型的参数，表示要唤醒的线程。</span></p>
  <p data-lake-id="u4d8f7c5b" id="u4d8f7c5b"><span data-lake-id="u10a20d43" id="u10a20d43">​</span><br></p>
  <p data-lake-id="u51e765f4" id="u51e765f4"><span data-lake-id="udf537b2a" id="udf537b2a">​</span><br></p>
 </body>
</html>